import logging
import os
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db import transaction
from django.db.models import Q
from django.http import FileResponse
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.authentication import TokenAuthentication
from rest_framework.parsers import JSONParser, MultiPartParser, FormParser
from rest_framework.utils import json
from rest_framework.views import APIView
from api_test.common.api_loadfile import import_api
from api_test.common.api_response import JsonResponse
from api_test.common.common import record_dynamic
from api_test.models import Project, ApiGroupLevelFirst, ApiInfo, ApiParameter, ApiResponse, ApiVersionLevelFirst, \
    ApiDataType, LoadFile
from api_test.serializers import ApiInfoSerializer, ApiInfoListSerializer, ApiInfoDeserializer, \
    ApiParameterDeserializer, ApiResponseDeserializer, ProjectSerializer, LoadFileSerializer, \
    LoadFileDeSerializer
from fotoable_api_test import settings


logger = logging.getLogger(__name__)  # 这里使用 __name__ 动态搜索定义的 logger 配置，这里有一个层次关系的知识点。


class ApiList(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="apiVersion_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="版本id"),
        openapi.Parameter(name="apiModule_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="模块id"),
        openapi.Parameter(name="name", in_=openapi.IN_QUERY, type=openapi.TYPE_STRING, description="接口名称"),

    ])
    def get(self, request):
        """
        获取接口列表
        """
        try:
            page_size = int(request.GET.get("page_size", 1000))
            page = int(request.GET.get("page", 1))
        except (TypeError, ValueError):
            return JsonResponse(code="999985", msg="page and page_size must be integer!")
        project_id = request.GET.get("project_id")
        first_module_id = request.GET.get("apiModule_id")
        first_version_id = request.GET.get("apiVersion_id")
        if not project_id:
            return JsonResponse(code="999996", msg="参数有误!")
        if not project_id.isdecimal():
            return JsonResponse(code="999996", msg="参数有误!")
        name = request.GET.get("name")
        try:
            pro_data = Project.objects.get(id=project_id, status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")
        # 判断是否传分组id，否则为所有接口列表
        obi = ApiInfo.objects.filter(project=project_id, status=True)
        if first_module_id:
            if not first_module_id.isdecimal():
                return JsonResponse(code="999996", msg="参数有误!")
            obi = obi.filter(apiModule=first_module_id)
        if first_version_id:
            if not first_version_id.isdecimal():
                return JsonResponse(code="999996", msg="参数有误!")
            obi = obi.filter(apiVersion=first_version_id)
        if name:
            obi = obi.filter(name__contains=name)
        obi = obi.order_by("id")
        paginator = Paginator(obi, page_size)  # paginator对象
        page_sizes = paginator.num_pages  # 总页数
        total = paginator.count
        try:
            obm = paginator.page(page)
        except PageNotAnInteger:
            obm = paginator.page(1)
        except EmptyPage:
            obm = paginator.page(paginator.num_pages)
        serialize = ApiInfoListSerializer(obm, many=True)
        return JsonResponse(data={"data": serialize.data,
                                  "page_sizes": page_sizes,
                                  "total": total
                                  }, code="999999", msg="成功!")


class ApiInfoDetail(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="api_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="api id"),
    ])
    def get(self, request):
        """
        获取接口详情
        """
        project_id = request.GET.get("project_id")
        api_id = request.GET.get("api_id")
        if not project_id or not api_id:
            return JsonResponse(code="999996", msg="参数有误!")
        if not project_id.isdecimal() or not api_id.isdecimal():
            return JsonResponse(code="999996", msg="参数有误!")
        try:
            pro_data = Project.objects.get(id=project_id, status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")
        try:
            obi = ApiInfo.objects.get(id=api_id, project=project_id, status=True)
            serialize = ApiInfoSerializer(obi)
            return JsonResponse(data=serialize.data, code="999999", msg="成功!")
        except ObjectDoesNotExist:
            return JsonResponse(code="999990", msg="接口已禁用or不存在!")


class AddApi(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验必传参数
            if not data.get("project_id") or not data.get("name") or not data.get("protocol") \
                    or not data.get("apiAddress") or not data.get("structure"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["project_id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            if data["protocol"] not in ["http", "https", "ws", "wss"]:
                return JsonResponse(code="999996", msg="参数有误!")

            if data['protocol'] in ['https', 'http']:
                if not data.get('requestType'):
                    return JsonResponse(code="999996", msg="参数有误!")
                elif data.get('requestType').upper() not in ['POST', 'PUT', 'DELETE', 'GET']:
                    return JsonResponse(code="999996", msg="参数有误!")
                data['requestType'] = data['requestType'].upper()

            if not data.get("apiModule_id") or not isinstance(data["apiModule_id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            if not data.get("apiVersion_id") or not isinstance(data["apiVersion_id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            request_list = data.get('requestList')
            if isinstance(request_list, str):
                request_list = json.loads(request_list)
                data['requestList'] = request_list
            elif isinstance(request_list, list):
                request_list = request_list
            else:
                return JsonResponse(code="999996", msg="参数requestList类型错误!")
            if request_list:
                for request in request_list:
                    for param in ['type_id', 'repeated', 'required', 'name']:
                        try:
                            request_param = request[param]
                            if not request_param and request_param is not False:
                                return JsonResponse(code="999996", msg=f"参数requestList错误,参数{param}不能为空")
                            if param == 'type_id':
                                if not ApiDataType.objects.filter(id=request_param, project_id=data['project_id']):
                                    return JsonResponse(code="999996", msg=f"参数requestList错误,项目{data['project_id']}"
                                                                           f"不存在参数类型type_id:{request_param}")
                        except KeyError:
                            return JsonResponse(code="999996", msg=f"参数requestList错误,缺少参数{param}")
            response_list = data.get('responseList')
            if isinstance(response_list, str):
                response_list = json.loads(response_list)
                data['responseList'] = response_list
            elif isinstance(response_list, list):
                response_list = response_list
            else:
                return JsonResponse(code="999996", msg="参数responseList类型错误!")
            if response_list:
                for response in response_list:
                    for param in ['type_id', 'name']:
                        try:
                            response_param = response[param]
                            if not response_param:
                                return JsonResponse(code="999996", msg=f"参数responseList错误,参数{param}不能为空")
                            if param == 'type_id':
                                if not ApiDataType.objects.filter(id=response_param, project_id=data['project_id']):
                                    return JsonResponse(code="999996", msg=f"参数requestList错误,项目{data['project_id']}"
                                                                           f"不存在参数类型type_id:{response_param}")
                        except KeyError:
                            return JsonResponse(code="999996", msg=f"参数responseList错误,缺少参数{param}")
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'name', 'apiModule_id', 'apiVersion_id', 'protocol', 'structure', 'apiAddress'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="接口名称"),
            'apiModule_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="模块id"),
            'apiVersion_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="版本id"),
            'protocol': openapi.Schema(type=openapi.TYPE_STRING, description="网络协议"),
            'structure': openapi.Schema(type=openapi.TYPE_STRING, description="通信协议"),
            'requestType': openapi.Schema(type=openapi.TYPE_STRING, description="请求类型"),
            'apiAddress': openapi.Schema(type=openapi.TYPE_STRING, description="接口路径"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="接口描述"),
            'requestList': openapi.Schema(type=openapi.TYPE_ARRAY, description="接口参数",
                                          items=openapi.Items(type=openapi.TYPE_OBJECT),
                                          default="[{'name': '参数名', 'type_id': 参数类型id, 'required': 是否必选, 'repeated': 是否list类型, 'description': ''}, ]"),
            'responseList': openapi.Schema(type=openapi.TYPE_ARRAY, description="响应参数",
                                           items=openapi.Items(type=openapi.TYPE_OBJECT),
                                           default="[{'name': '参数名', 'type_id': 参数类型id, 'repeated': 是否list类型, 'description': ''}, ]"),
        },
    ))
    def post(self, request):
        """
        新增接口
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        data["userUpdate"] = request.user.pk
        try:
            obj = Project.objects.get(id=data["project_id"], status=True)
            if not request.user.is_superuser and obj.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")

        count = ApiInfo.objects.filter(name=data["name"], project=data["project_id"], status=True).count()
        if count > 0:
            return JsonResponse(code="999997", msg="存在相同名称!")
        else:
            with transaction.atomic():  # 执行错误后，帮助事务回滚
                serialize = ApiInfoDeserializer(data=data)
                if serialize.is_valid():
                    try:
                        obm = ApiGroupLevelFirst.objects.get(id=data["apiModule_id"], project=data["project_id"], status=True)
                        obv = ApiVersionLevelFirst.objects.get(id=data["apiVersion_id"], project=data["project_id"], status=True)
                        serialize.save(project=obj, apiModule=obm, apiVersion=obv)
                    except KeyError:
                        serialize.save(project=obj)
                    except ObjectDoesNotExist:
                        return JsonResponse(code="999991", msg="该项目下不存在该模块or版本!")
                    api_id = serialize.data.get("id")
                    if data.get("requestList") and len(data.get("requestList")):
                        for i in data["requestList"]:
                            if i.get("name"):
                                i["api"] = api_id
                                param_serialize = ApiParameterDeserializer(data=i)
                                if param_serialize.is_valid():
                                    obtype = ApiDataType.objects.get(id=i["type_id"], project=data["project_id"],
                                                                        status=True)
                                    param_serialize.save(api=ApiInfo.objects.get(id=api_id), type=obtype)
                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiParameter创建失败,'
                                                                         '失败原因:参数requestList错误',
                                                        data=param_serialize.errors)
                                     # TODO 查看save失败的原因
                    if data.get("responseList") and len(data.get("responseList")):
                        for i in data["responseList"]:
                            if i.get("name"):
                                i["api"] = api_id
                                response_serialize = ApiResponseDeserializer(data=i)
                                if response_serialize.is_valid():
                                    obtype = ApiDataType.objects.get(id=i["type_id"], project=data["project_id"],
                                                                        status=True)
                                    response_serialize.save(api=ApiInfo.objects.get(id=api_id), type=obtype)
                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiResponse创建失败,'
                                                                         '失败原因:参数responseList错误',
                                                        data=response_serialize.errors)
                    record_dynamic(project=data["project_id"],
                                   _type="新增", operationObject="接口", user=request.user.pk,
                                   data="新增接口“%s”" % data["name"])
                    return JsonResponse(code="999999", msg="成功!", data={"api_id": api_id})
                return JsonResponse(code="999996", msg="参数有误!")


class UpdateApi(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            if not data.get("project_id") or not data.get("name") or not data.get("protocol") or not \
                    data.get("structure") or not data.get("apiAddress") or not data.get("id") or \
                    'apiVersion_id' not in data or 'apiModule_id' not in data:
                return JsonResponse(code="999996", msg="参数1有误!")
            if not isinstance(data["project_id"], int) or not isinstance(data["id"], int):
                return JsonResponse(code="999996", msg="参数2有误!")
            if data["protocol"].upper() not in ["HTTP", "HTTPS", "WS", "WSS"]:
                return JsonResponse(code="999996", msg="参数有误!")
            else:
                data["protocol"] = data["protocol"].lower()

            if data['protocol'] in ['https', 'http']:
                if not data.get('requestType'):
                    return JsonResponse(code="999996", msg="参数有误!")
                elif data.get('requestType').upper() not in ['POST', 'PUT', 'DELETE', 'GET']:
                    return JsonResponse(code="999996", msg="参数有误!")
                data['requestType'] = data['requestType'].upper()

            if not isinstance(data["apiModule_id"], int) or not isinstance(data["apiVersion_id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            request_list = data.get('requestList')
            if isinstance(request_list, str):
                request_list = json.loads(request_list)
                data['requestList'] = request_list
            elif isinstance(request_list, list):
                request_list = request_list
            else:
                return JsonResponse(code="999996", msg="参数requestList类型错误!")
            if request_list:
                for request in request_list:
                    for param in ['type_id', 'repeated', 'required', 'name']:
                        try:
                            request_param = request[param]
                            if not request_param and request_param is not False:
                                return JsonResponse(code="999996", msg=f"参数requestList错误,参数{param}不能为空")
                            if param == 'type_id':
                                if not ApiDataType.objects.filter(id=request_param, project_id=data['project_id']):
                                    return JsonResponse(code="999996", msg=f"参数requestList错误,项目{data['project_id']}"
                                                                           f"不存在参数类型type_id:{request_param}")
                        except KeyError:
                            return JsonResponse(code="999996", msg=f"参数requestList错误,缺少参数{param}")

            response_list = data.get('responseList')
            if isinstance(response_list, str):
                response_list = json.loads(response_list)
                data['responseList'] = response_list
            elif isinstance(response_list, list):
                response_list = response_list
            else:
                return JsonResponse(code="999996", msg="参数responseList类型错误!")
            if response_list:
                for response in response_list:
                    for param in ['type_id', 'name']:
                        try:
                            response_param = response[param]
                            if not response_param:
                                return JsonResponse(code="999996", msg=f"参数responseList错误,参数{param}不能为空")
                            if param == 'type_id':
                                if not ApiDataType.objects.filter(id=response_param, project_id=data['project_id']):
                                    return JsonResponse(code="999996", msg=f"参数requestList错误,项目{data['project_id']}"
                                                                           f"不存在参数类型type_id:{response_param}")
                        except KeyError:
                            return JsonResponse(code="999996", msg=f"参数responseList错误,缺少参数{param}")
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'name', 'apiModule_id', 'apiVersion_id', 'protocol', 'structure', 'apiAddress'],
        properties={
            'id': openapi.Schema(type=openapi.TYPE_INTEGER, description="接口id"),
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="接口名称"),
            'apiModule_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="模块id"),
            'apiVersion_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="版本id"),
            'protocol': openapi.Schema(type=openapi.TYPE_STRING, description="网络协议"),
            'structure': openapi.Schema(type=openapi.TYPE_STRING, description="通信协议"),
            'requestType': openapi.Schema(type=openapi.TYPE_STRING, description="请求类型"),
            'apiAddress': openapi.Schema(type=openapi.TYPE_STRING, description="接口路径"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="接口描述"),
            'requestList': openapi.Schema(type=openapi.TYPE_ARRAY, description="接口参数",
                                          items=openapi.Items(type=openapi.TYPE_OBJECT),
                                          default="[{'id': request_id, 'api'：api_id, 'name': '参数名', 'type_id': 参数类型id, 'required': 是否必选, 'repeated': 是否list类型, 'description': ''}, ]"),
            'responseList': openapi.Schema(type=openapi.TYPE_ARRAY, description="响应参数",
                                           items=openapi.Items(type=openapi.TYPE_OBJECT),
                                           default="[{'id': response_id, 'api'：api_id, 'name': '参数名', 'type_id': 参数类型id, 'repeated': 是否list类型, 'description': ''}, ]"),
        },
    ))
    def post(self, request):
        """
        修改接口
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        data["userUpdate"] = request.user.pk
        project_id = data['project_id']
        try:
            pro_data = Project.objects.get(id=project_id, status=True)
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")
        count = ApiInfo.objects.filter(name=data["name"], project=project_id, status=True).exclude(id=data["id"]).count()
        if count > 0:
            return JsonResponse(code="999997", msg="存在相同名称!")
        try:
            obi = ApiInfo.objects.get(id=data["id"], status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999990", msg="接口不存在or已禁用!")
        with transaction.atomic():
            serialize = ApiInfoDeserializer(data=data)
            if serialize.is_valid():
                data["userUpdate"] = request.user
                try:
                    ApiGroupLevelFirst.objects.get(id=data["apiModule_id"], project=data["project_id"])
                    ApiVersionLevelFirst.objects.get(id=data["apiVersion_id"], project=data["project_id"])
                    serialize.update(instance=obi, validated_data=data)
                except KeyError:
                    serialize.update(instance=obi, validated_data=data)
                except ObjectDoesNotExist:
                    return JsonResponse(code="999991", msg="模块or版本不存在!")
                api_param = Q()
                if data.get("requestList") and len(data.get("requestList")):
                    for i in data["requestList"]:
                        if i.get("api") and i.get("id"):
                            api_param = api_param | Q(id=i["id"])
                            if i["name"]:
                                param_serialize = ApiParameterDeserializer(data=i)
                                if param_serialize.is_valid():
                                    i["api"] = ApiInfo.objects.get(id=i["api"])
                                    param_serialize.update(instance=ApiParameter.objects.get(id=i["id"]),
                                                           validated_data=i)
                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiParameter创建失败,'
                                                                         '失败原因:参数requestList错误',
                                                        data=param_serialize.errors)
                        else:
                            if i.get("name"):
                                i["api_id"] = data['id']
                                param_serialize = ApiParameterDeserializer(data=i)
                                if param_serialize.is_valid():
                                    param_serialize.save(api=ApiInfo.objects.get(id=data["id"]),
                                                         type=ApiDataType.objects.get(id=i["type_id"]))
                                    api_param = api_param | Q(id=param_serialize.data.get("id"))

                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiParameter创建失败,'
                                                                         '失败原因:参数requestList错误',
                                                        data=param_serialize.errors)
                ApiParameter.objects.exclude(api_param).filter(api=data["id"]).delete()
                api_response = Q()
                if data.get("responseList") and len(data.get("responseList")):
                    for i in data["responseList"]:
                        if i.get("api") and i.get("id"):
                            api_response = api_response | Q(id=i["id"])
                            if i["name"]:
                                response_serialize = ApiResponseDeserializer(data=i)
                                if response_serialize.is_valid():
                                    i["api"] = ApiInfo.objects.get(id=i["api"])
                                    response_serialize.update(instance=ApiResponse.objects.get(id=i["id"]),
                                                              validated_data=i)
                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiResponse创建失败,'
                                                                         '失败原因:参数responseList错误',
                                                        data=response_serialize.errors)
                        else:
                            if i.get("name"):
                                i["api"] = data['id']
                                response_serialize = ApiResponseDeserializer(data=i)
                                if response_serialize.is_valid():
                                    param_type = ApiDataType.objects.filter(id=i['type_id'], project_id=project_id)
                                    response_serialize.save(api=ApiInfo.objects.get(id=data["id"]),
                                                            type=param_type[0])
                                    api_response = api_response | Q(id=response_serialize.data.get("id"))
                                else:
                                    return JsonResponse(code=999995, msg='api创建成功,apiResponse创建失败,'
                                                                         '失败原因:参数responseList错误',
                                                        data=response_serialize.errors)
                ApiResponse.objects.exclude(api_response).filter(api=data["id"]).delete()
                record_dynamic(project=data["project_id"],
                               _type="修改", operationObject="接口", user=request.user.pk,
                               data="修改接口“%s”" % data["name"])
                return JsonResponse(code="999999", msg="成功!")
            return JsonResponse(code="999995", msg="参数有误!", data=serialize.errors)


class DelApi(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        若接口下有case，则不允许删除
        """
        try:
            # 校验project_id, id类型为int
            if not data.get("project_id") or not data.get("ids"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["project_id"], int) or not isinstance(data["ids"], list):
                return JsonResponse(code="999996", msg="参数有误!")
            for i in data["ids"]:
                if not isinstance(i, int):
                    return JsonResponse(code="999996", msg="参数有误!")
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'ids'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_INTEGER),
                                  description="待删除待接口id列表"),
        },
    ))
    def post(self, request):
        """
        删除接口
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"])
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在!")
        pro_data = ProjectSerializer(pro_data)
        if not pro_data.data["status"]:
            return JsonResponse(code="999985", msg="该项目已禁用")

        # 校验待删除待的接口下是否存在case
        error_infos = ""
        try:
            for j in data["ids"]:
                count = ApiInfo.objects.get(id=j, project=data["project_id"],
                                            status=True).api_info.filter(status=True).count()
                if count > 0:
                    name = ApiInfo.objects.get(id=j).name
                    error_infos = error_infos + "接口" + name + "包含用例无法删除"
            if len(error_infos) > 0:
                return JsonResponse(code="999996", msg="失败!" + error_infos + ", 请删除用例后，重新选择删除")
        except ObjectDoesNotExist:
                return JsonResponse(code="999995", msg="该项目不存在该接口!")

        name_list = []

        for j in data["ids"]:
            obj = ApiInfo.objects.get(id=j, project=data["project_id"])
            if obj:
                obj.status = False
                obj.save()
                name_list.append(str(obj.name))
        record_dynamic(project=data["project_id"],
                       _type="禁用", operationObject="接口", user=request.user.pk, data="禁用接口列表“%s”" % name_list)
        return JsonResponse(code="999999", msg="成功!")


class ImportFileApi(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验project_id, id类型为int
            if not data.get("project_id") or not data.get("apiVersion_id") or not data.get("apiModule_id"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["project_id"], int) or not isinstance(data["ids"], list) \
                    or not isinstance(data["apiVersion_id"], int) or not isinstance(data["apiModule_id"], int):
                return JsonResponse(code="999996", msg="参数类型有误!")
        except KeyError:
            return JsonResponse(code="999996", msg="参数未知错误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'ids', 'apiVersion_id', 'apiModule_id', 'protocol', 'apiAddress'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_INTEGER), description="待上传文件id列表"),
            'apiModule_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="模块id"),
            'apiVersion_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="版本id"),
            'protocol': openapi.Schema(type=openapi.TYPE_STRING, description="网络协议"),
            'requestType': openapi.Schema(type=openapi.TYPE_STRING, description="请求类型"),
            'apiAddress': openapi.Schema(type=openapi.TYPE_STRING, description="接口路径"),
        },
    ))
    def post(self, request):
        """
        批量导入接口信息pb/json/xml
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"], status=True)
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")

        try:
            ApiGroupLevelFirst.objects.get(id=data["apiModule_id"], project=data["project_id"], status=True)
            ApiVersionLevelFirst.objects.get(id=data["apiVersion_id"], project=data["project_id"], status=True)
            # 检测所选文件是否为同一类型的文件 pb支持多个文件，xml支持一个文件
            filetype_check = []
            ids_len =len(data["ids"])
            for i in data["ids"]:
                loadfile = LoadFile.objects.get(id=i, project=data["project_id"], status=True)
                file_name = loadfile.file.name
                file_type = file_name.split('.')[-1]
                if file_type not in filetype_check:
                    filetype_check.append(file_type)
            if len(filetype_check) > 1:
                return JsonResponse(code="999995", msg="所选择的文件类型不同，无法批量导入!")
            if ids_len > 1 and "xml" in filetype_check:
                return JsonResponse(code="999995", msg="选择的xml文件超过1个，目前只支持单个xml文件批量导入!")

        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="模块/版本/文件 不存在or已禁用!")

        try:
            api_ids = import_api(filetype_check[0], data["ids"], data["project_id"], data["apiVersion_id"], data["apiModule_id"], request.user.pk, data["apiAddress"], data["protocol"], data["requestType"])
            return JsonResponse(code="999999", msg="成功!", data=api_ids)
        except Exception as e:
            logging.exception(e)
            return JsonResponse(code="999998", msg="失败!")


class FileList(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="system", in_=openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, description="系统模版"),
    ])
    def get(self, request):
        """
        文件列表
        """
        project_id = request.GET.get("project_id")
        system = request.GET.get("system")

        # 校验参数
        if not project_id:
            return JsonResponse(code="999996", msg="参数有误!")
        if not project_id.isdecimal():
            return JsonResponse(code="999996", msg="参数有误!")
        # 验证项目是否存在
        try:
            Project.objects.get(id=project_id, status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")
        fileload = LoadFile.objects.filter(project=project_id, status=True)
        if system:
            fileload = fileload.filter(system=system)
        fileload = fileload.order_by("id")
        serialize = LoadFileSerializer(fileload, many=True)
        return JsonResponse(data=serialize.data, code="999999", msg="成功!")


class UploadFile(APIView):
    parser_classes = (MultiPartParser, FormParser)
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验project_id, id类型为int
            if not data.get("project_id") or not data.get("name") or not data.get("file"):
                return JsonResponse(code="999996", msg="参数有误!")
        except KeyError:
            return JsonResponse(code="999996", msg="参数未知错误!")

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_FORM, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="name", in_=openapi.IN_FORM, type=openapi.TYPE_STRING, description="待上传的文件名称"),
        openapi.Parameter(name="file", in_=openapi.IN_FORM, type=openapi.TYPE_FILE, description="待上传的文件"),
    ])
    def post(self, request):
        """
        上传单个文件
        """
        data = request.data.dict()
        result = self.parameter_check(data)
        if result:
            return result
        data["user_id"] = request.user.pk
        try:
            pro_data = Project.objects.get(id=data["project_id"], status=True)
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")

        filename = data["file"]._name
        # 上传前将本地的文件删除，将数据库相同name的记录删除
        LoadFile.objects.filter(name=data["name"], project=data["project_id"], status=True).delete()
        file_full_name = os.path.join(settings.MEDIA_ROOT, 'loadfile', filename)
        if os.path.isfile(file_full_name):
            os.remove(file_full_name)
        file_serializer = LoadFileDeSerializer(data=request.data)
        if file_serializer.is_valid():
            file_serializer.save(project=pro_data, user=User.objects.get(id=data["user_id"]))
            # file_serializer.update(instance=loadfile, validated_data=data)
            record_dynamic(project=data["project_id"], _type="上传", operationObject="文件列表",
                           user=request.user.pk, data="上传文件“%s”" % data["name"])
            return JsonResponse(code="999999", msg="成功")
        else:
            return JsonResponse(code="999999", msg="失败", data=file_serializer.errors)


class DownloadFile(APIView):
    # parser_classes = (MultiPartParser, FormParser)
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="文件id"),
    ])
    def get(self, request):
        """
        下载单个文件
        """
        project_id = request.GET.get("project_id")
        id = request.GET.get("id")
        try:
            Project.objects.get(id=project_id, status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")

        file_load = LoadFile.objects.get(id=id, project_id=project_id, status=True)
        file = open(file_load.file.path, 'rb')
        # with open(file_load.file.path, 'rb') as file:  # 报错
        file_name = file_load.file.name.split("/")[1]
        response = FileResponse(file)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename="%s"' %(file_name)
        # record_dynamic(project=project_id, _type="下载", operationObject="文件列表",
        #                user=request.user.pk, data="下载文件“%s”" % file_name)
        return response


class DeleteFile(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验project_id, id类型为int
            if not isinstance(data["ids"], list) or not isinstance(data["project_id"], int):
                for i in data["ids"]:
                    if not isinstance(i, int) or not isinstance(int(i), int):
                        return JsonResponse(code="999995", msg="参数有误！")
                return JsonResponse(code="999995", msg="参数有误！")
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'ids'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_INTEGER),
                                  description="待删除文件id列表"),
        },
    ))
    def post(self, request):
        """
        删除(禁用)上传的文件
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"], status=True)
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")
        # 根据项目id和模块 id查找，若存在则删除
        try:
            for j in data["ids"]:
                obj = LoadFile.objects.get(id=j, project=data["project_id"])
                if obj:
                    # obj.delete()  # 删除
                    del_name = os.path.basename(obj.file.path) + ".del"
                    if os.path.isfile(obj.file.path):
                        os.rename(obj.file.path,  os.path.join(os.path.dirname(obj.file.path), del_name))
                    obj.status = False
                    obj.save()
                    record_dynamic(project=data["project_id"], _type="禁用", operationObject="文件列表",
                                   user=request.user.pk, data="禁用文件“%s”" % os.path.basename(obj.file.path))
            return JsonResponse(code="999999", msg="成功！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="文件不存在！")
        except Exception as e:
            return JsonResponse(code="999995", msg="出错啦", data=e)
